package com.feiyun.util;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.web.multipart.MultipartFile;

/**
 * @ClassName ExcleUtils
 * @author: xingming
 * @Description:
 * @time 2023/04/02 12:45:32
 * @Version 1.0
 */

public class ExcleUtils {

    /**
     * 解析Excel文件并将数据反射到实体类中
     *
     * @param file        Excel文件
     * @param entityClass 实体类的Class对象
     * @param <T>         实体类的类型
     * @return 实体类对象的列表
     * @throws Exception
     */
    public static <T> List<T> parseExcel(MultipartFile file, Class<T> entityClass) throws Exception {
        List<T> entities = new ArrayList<>();

        // 创建Workbook对象
        Workbook workbook = WorkbookFactory.create(file.getInputStream());

        // 获取第一个Sheet对象
        Sheet sheet = workbook.getSheetAt(0);

        // 获取第一行，即实体类的字段名
        Row headerRow = sheet.getRow(0);
        List<String> fieldNames = new ArrayList<>();
        for (Cell cell : headerRow) {
            fieldNames.add(cell.getStringCellValue());
        }

        // 遍历每一行，创建实体类对象并将数据反射到实体类中
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            T entity = entityClass.newInstance();
            for (int j = 0; j < fieldNames.size(); j++) {
                Cell cell = row.getCell(j);
                String fieldName = fieldNames.get(j);
                Field field = entityClass.getDeclaredField(fieldName);
                field.setAccessible(true);
                Object value = getCellValue(cell, field.getType());
                field.set(entity, value);
            }
            entities.add(entity);
        }

        return entities;
    }

    /**
     * 根据单元格的数据类型返回对应的Java对象
     *
     * @param cell      单元格对象
     * @param fieldType 字段类型
     * @return 对应的Java对象
     */
    private static Object getCellValue(Cell cell, Class<?> fieldType) {
        if (cell == null) {
            return null;
        }
        if (fieldType == String.class) {
            if (cell.getCellType() == CellType.NUMERIC) {
                return String.valueOf((long) cell.getNumericCellValue());
            } else {
                return cell.getStringCellValue();
            }
        } else if (fieldType == Integer.class || fieldType == int.class) {
            return (int) cell.getNumericCellValue();
        } else if (fieldType == Double.class || fieldType == double.class) {
            return cell.getNumericCellValue();
        } else if (fieldType == Byte.class || fieldType == byte.class) {
            return (byte) cell.getNumericCellValue();
        } else if (fieldType == Boolean.class || fieldType == boolean.class) {
            if (cell.getCellType() == CellType.BOOLEAN) {
                return cell.getBooleanCellValue();
            } else if (cell.getCellType() == CellType.NUMERIC) {
                return cell.getNumericCellValue() != 0;
            } else if (cell.getCellType() == CellType.STRING) {
                return Boolean.parseBoolean(cell.getStringCellValue());
            } else {
                throw new IllegalStateException("Cannot get a BOOLEAN value from a " + cell.getCellType() + " cell");
            }
        } else if (fieldType == LocalDate.class) {
            return cell.getLocalDateTimeCellValue().toLocalDate();
        } else if (fieldType == LocalDateTime.class) {
            return cell.getLocalDateTimeCellValue();
        } else if (fieldType == Short.class || fieldType == short.class) {
            return (short) cell.getNumericCellValue();
        } else if (fieldType == Date.class) {
            return cell.getDateCellValue();
        } else {
            throw new IllegalArgumentException("Unsupported field type: " + fieldType);
        }
    }
}